package com.snopy.concurrency.base;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.LockSupport;

/**
 * @author snopy
 * @version 1.0.0
 * @classname FIFOMutex
 * @description
 * @email 77912204@qq.com
 * @date 2022/06/24 15:39
 */
public class FIFOMutex {
    private final AtomicBoolean locked = new AtomicBoolean(false);
    private final Queue<Thread> waiters = new ConcurrentLinkedDeque<>();

    public void lock(){
        boolean wasInterrupted = false;
        Thread current = Thread.currentThread();
        waiters.add(current);

        //不是第一个或获取不到锁时阻塞
        while (waiters.peek()!=current||!locked.compareAndSet(false,true)){
            LockSupport.park(this);
            if (Thread.interrupted()){
                wasInterrupted = true;
            }
        }
        waiters.remove();
        if (wasInterrupted){
            current.interrupt();
        }

    }
    public void unpark(){
        locked.set(false);
        LockSupport.unpark(waiters.peek());
    }


}
